﻿using OpenVision.Data;
using OpenVision.Models;
using OpenVision.Repositories;
using OpenVisionWebService.Models;
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using System.Web.Http.Cors;

namespace OpenVisionWebService.Controllers
{
    [EnableCors(origins: "http://dogdream.apphb.com", headers: "*", methods: "*")]
    public class UsersController : BaseController
    {
        private readonly IUserRepository data;

        public UsersController()
        {
            this.data = new DbUsersRepository(new OpenVisionContext());
        }

        public UsersController(IUserRepository repository)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("Invalid repository! It cannot be null!");
            }

            this.data = repository;
        }

        [HttpPost]
        [ActionName("register")]
        public HttpResponseMessage RegisterUser([FromBody]
                                                UserRegisterModel model)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                if (!ModelState.IsValid)
                {
                    throw new Exception("Invalid user register model!");
                }

                User user = model.ToUser();

                var dbUser = this.data.Add(user);
                var userLoggedModel = UserLoggedModel.CreateModel(dbUser);

                var response = this.Request.CreateResponse<UserLoggedModel>(HttpStatusCode.Created, userLoggedModel);
                var resourceLink = Url.Link("UsersGetApi", new { id = userLoggedModel.Id });
                response.Headers.Location = new Uri(resourceLink);
                return response;
            });
        }

        [HttpPost]
        [ActionName("login")]
        public HttpResponseMessage LoginUser([FromBody]
                                             UserLoginModel model)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                if (!ModelState.IsValid)
                {
                    throw new Exception("Invalid user login model!");
                }

                User dbUser = this.data.Get(model.Nickname);

                if (dbUser == null || model.Password != dbUser.Password)
                {
                    throw new Exception("Invalid nickname or password!");
                }

                User loggedUser = this.data.LoginUser(dbUser);
                UserLoggedModel loggedModel = UserLoggedModel.CreateModel(loggedUser);

                var response = this.Request.CreateResponse<UserLoggedModel>(HttpStatusCode.OK, loggedModel);
                return response;
            });
        }

        [HttpGet]
        [ActionName("logout")]
        public HttpResponseMessage LogoutUser(string sessionKey)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                this.data.LogoutUser(sessionKey);

                var response = this.Request.CreateResponse(HttpStatusCode.OK, "User logged out successfully");
                return response;
            });
        }

        [HttpGet]
        [ActionName("get")]
        public UserDetailsModel Get(int id)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                var user = this.data.Get(id);
                var userModel = UserDetailsModel.CreateModel(user);

                return userModel;
            });
        }

        [HttpPut]
        [ActionName("position")]
        public HttpResponseMessage UpdatePosition(string sessionKey, [FromBody]
                                                  UserPositionModel model)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                this.data.UpdatePosition(model.Longitude, model.Latitude, sessionKey);

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            });
        }

        [HttpPut]
        [ActionName("range")]
        public HttpResponseMessage UpdateRange(string sessionKey, [FromBody]
                                               UserRangeModel model)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                this.data.UpdateRange(model.Range, sessionKey);

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            });
        }

        [HttpPut]
        [ActionName("message")]
        public HttpResponseMessage UpdateMessage(string sessionKey, [FromBody]
                                                 UserMessageModel model)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                this.data.UpdateMessage(model.Message, sessionKey);

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            });
        }

        [HttpPut]
        [ActionName("call")]
        public HttpResponseMessage UpdateMessage(string sessionKey)
        {
            return base.PerformOperationAndHandleExceptions(() =>
            {
                this.data.UpdateCallButton(sessionKey);

                var response = this.Request.CreateResponse(HttpStatusCode.OK);
                return response;
            });
        }
    }
}